﻿namespace Manhua2.Pages
{
    using Manhua2.Common;
    using Manhua2.DataModel;
    using Manhua2.Helper;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Windows.Foundation.Collections;
    using Windows.Storage.Pickers;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Xaml.Navigation;

    /// <summary>
    /// 基本页，提供大多数应用程序通用的特性。
    /// </summary>
    public sealed partial class LocalFileViewPageNew : Page
    {
        #region 基础数据
        private ViewPageModel config = new ViewPageModel();
        private List<ComicPage> pages;         
        private int _curPage;

        public int CurPage
        {
            get { return _curPage; }
            set { _curPage = value; }
        }

        public int? Part
        {
            get;
            set;
        }

        public int MaxPage { get; set; }
        #endregion

        public LocalFileViewPageNew()
        {
            this.InitializeComponent();

            this.DataContext = this.config;
            this.direction.IsOn = Global.ClientOption.L2R;
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e) 
        {
            // 离开页面时释放内存

            try
            {
                foreach (var page in this.pages)
                {
                    try
                    {
                        if (page.SourceStream != null)
                            page.SourceStream.Dispose();
                    }
                    catch
                    {
                    }
                }

                Global.FileProvider.Dispose();
            }
            catch
            {
            }
        }

        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (Global.FileProvider == null) this.Frame.Navigate(typeof(MainPage));
            string error = null;

            try
            {
                // 加载中...
                this.config.Loading = true;

                using (ModelContext context = new ModelContext())
                {
                    this.pages = await Global.FileProvider.GetPagesAsync();
                    if (this.pages != null)
                    {
                        this.MaxPage = this.pages.Max(k => k.Page);
                    }

                    this.config.ComicTitle = Global.FileProvider.LocalName;

                    // 总页数
                    this.config.TotalPage = this.MaxPage.ToString();

                    // 漫画显示控制
                    this.CurPage = 1;
                    this.OnPageChanged(true);
                }
            }
            catch (Exception ex)
            {
                error = ex.Message;
            }

            // 加载完毕
            this.config.Loading = false;

            await MethodHelper.ShowMessageDialogNotEmpty(error);
        }
       
        #region 触控翻页操作
        private void Page_Tapped(object sender, TappedRoutedEventArgs e)
        {
            if (this.pages == null || this.pages.Count == 0) return;
            var point = e.GetPosition(this);
            if (point.X <= this.ActualWidth / 3)
            {
                if (!this.direction.IsOn)
                {
                    this.PreviousPage();
                }
                else
                {
                    this.NextPage();
                }

                return;
            }

            if (point.X >= this.ActualWidth / 3 * 2)
            {
                if (!this.direction.IsOn)
                {
                    this.NextPage();
                }
                else
                {
                    this.PreviousPage();
                }

                return;
            }
        }

        private void Page_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
        {
            this.scrollViewer.ZoomToFactor(1.0f);
        }
        #endregion

        private void GoBack(object sender, RoutedEventArgs e)
        {
            this.Frame.Navigate(typeof(MainPage));
        }

        private void Image_ImageOpened(object sender, RoutedEventArgs e)
        {
            this.config.Loading = false;
        }

        private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            MethodHelper.ShowMessageDialog(e.ErrorMessage);
        }

        /// <summary>
        /// 返回主页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnHome_Click(object sender, RoutedEventArgs e)
        {
            this.Frame.Navigate(typeof(MainPage));
        }

        private async void btnDetail_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new MessageDialog(
                    "1. 打开目录下的所有图片文件(建议使用此方式管理文件)\r\n" +
                    "2. 打开zip或rar压缩包中的图片文件(不支持密码)\r\n" +
                    "注意, 图片加载是一次性加载, 请不要打开过于庞大的文件或文件夹.",
                    "提示");

            dialog.Commands.Add(new UICommand("打开目录", (cmd) => { }, 1));
            dialog.Commands.Add(new UICommand("打开文件", (cmd) => { }, 2));
            dialog.Commands.Add(new UICommand("取消", (cmd) => { }, 3));

            var command = await dialog.ShowAsync();
            switch ((int)command.Id)
            {
                case 1:
                    {
                        FolderPicker picker = new FolderPicker();
                        picker.FileTypeFilter.Add(".jpg");
                        picker.FileTypeFilter.Add(".bmp");
                        picker.FileTypeFilter.Add(".png");
                        var folder = await picker.PickSingleFolderAsync();
                        if (folder != null)
                        {
                            Global.FileProvider = new Provider.LocalFileProvider(folder);
                            this.Frame.Navigate(typeof(LocalFileViewPageNew));
                        }
                    }

                    break;

                case 2:
                    {
                        FileOpenPicker picker = new FileOpenPicker();
                        picker.FileTypeFilter.Add(".zip");
                        picker.FileTypeFilter.Add(".rar");

                        var file = await picker.PickSingleFileAsync();
                        if (file != null)
                        {
                            Global.FileProvider = new Provider.LocalFileProvider(file);
                            this.Frame.Navigate(typeof(LocalFileViewPageNew));
                        }
                    }
                    break;

                default:
                    break;
            }
        }

        /// <summary>
        /// 图片放大
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnZoomIn_Click(object sender, RoutedEventArgs e)
        {
            // 计算放大比例
            this.config.Scale += 0.25f;
            this.config.Scale = this.config.Scale > this.config.MaxScale ? this.config.MaxScale : this.config.Scale;
            this.scrollViewer.ZoomToFactor(this.config.Scale);
        }

        /// <summary>
        /// 图片缩小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnZoomOut_Click(object sender, RoutedEventArgs e)
        {
            // 计算缩小比例
            this.config.Scale -= 0.25f;
            this.config.Scale = this.config.Scale < this.config.MinScale ? this.config.MinScale : this.config.Scale;
            this.scrollViewer.ZoomToFactor(this.config.Scale);
        }

        /// <summary>
        /// 漫画页面跳转
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGo_Click(object sender, RoutedEventArgs e)
        {
            if (this.pages == null ||
                this.pages.Count == 0)
                return;
            int page;
            if (!int.TryParse(this.txtGoPage.Text, out page))
                return;

            if (page > this.MaxPage ||
                page < 1)
                return;

            this.CurPage = page;

            if (this.rdoAutoHalf.IsChecked == true)
            {
                this.Part = 1;
            }

            this.OnPageChanged(true);
        }
        
        private void btnPreviousPage_Click(object sender, RoutedEventArgs e)
        {
            if (this.pages == null || this.pages.Count == 0) return;
            this.PreviousPage();
        }

        private void btnNextPage_Click(object sender, RoutedEventArgs e)
        {
            if (this.pages == null || this.pages.Count == 0) return;
            this.NextPage();
        }

        private void txtGoPage_KeyDown(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == Windows.System.VirtualKey.Enter)
            {
                this.btnGo_Click(null, null);
            }
        }

        #region 辅助方法
        /// <summary>
        /// 翻页
        /// </summary>
        private async void OnPageChanged(bool isNextPage)
        {
            try
            {
                if (this.pages == null || this.pages.Count == 0) return;

                var page = this.pages.Where(k => k.Page == this.CurPage).FirstOrDefault();
                if (page == null) return;
                this.config.Loading = true;

                await this.SetImageAsync(page, isNextPage);
            }
            catch
            {
            }
        }

        private void NextPage()
        {
            var mode = this.GetPageMode();
            switch (mode)
            {
                case PageMode.Normal:
                    if (this.CurPage < this.MaxPage)
                    {
                        this.Part = null;
                        this.CurPage++;
                    }

                    break;

                case PageMode.AutoHalf:
                    if (this.CurPage < this.MaxPage ||
                       (this.CurPage == this.MaxPage && this.Part == 1))
                    {
                        if (this.Part == 2 || this.Part == null)
                        {
                            this.CurPage++;
                            this.Part = this.pages.Where(k => k.Page == this.CurPage).FirstOrDefault().IsPart ?
                                new Nullable<int>(1) : null;
                        }
                        else if (this.Part == 1)
                            this.Part++;
                        else
                            throw new ArgumentException("Part");
                    }

                    break;

                case PageMode.AutoMerge:
                    if (this.CurPage < this.MaxPage - 1)
                    {
                        this.CurPage += 2;
                    }
                    else
                    {
                        if (this.CurPage == this.MaxPage - 1)
                        {
                            this.CurPage += 1;
                        }
                    }

                    break;
            }

            this.OnPageChanged(true);
        }

        private void PreviousPage()
        {
            var mode = this.GetPageMode();
            switch (mode)
            {
                case PageMode.Normal:
                    if (this.CurPage > 1)
                    {
                        this.Part = null;
                        this.CurPage -= 1;
                    }

                    break;

                case PageMode.AutoHalf:
                    if (this.CurPage > 1 ||
                    (this.CurPage == 1 && this.Part == 2))
                    {
                        if (this.Part == 1 || this.Part == null)
                        {
                            this.CurPage -= 1;
                            this.Part = this.pages.Where(k => k.Page == this.CurPage).Count() > 1 ?
                                new Nullable<int>(2) : null;
                        }
                        else if (this.Part == 2)
                            this.Part -= 1;
                        else
                            throw new ArgumentException("Part");
                    }

                    break;

                case PageMode.AutoMerge:
                    if (this.CurPage > 2)
                    {
                        this.CurPage -= 2;
                    }
                    else if (this.CurPage == 2)
                    {
                        this.CurPage -= 1;
                    }

                    break;
            }

            this.OnPageChanged(false);
        }

        private PageMode GetPageMode()
        {
            if (this.rdoAutoHalf.IsChecked == true)
            {
                return PageMode.AutoHalf;
            }

            if (this.rdoAutoMerge.IsChecked == true)
            {
                return PageMode.AutoMerge;
            }

            return PageMode.Normal;
        }

        private async Task SetImageAsync(ComicPage page, bool isNextPage)
        {
            do
            {
                image.Source = null;

                var mode = this.GetPageMode();
                if (mode == PageMode.Normal)
                {
                    this.config.Page = page.Page.ToString();
                    image.Source = await page.SourceStream.GetBitmapAsync();
                    break;
                }

                if (mode == PageMode.AutoHalf)
                {
                    if (this.Part != null)
                    {
                        this.config.Page = page.Page + "-" + this.Part.ToString();
                        this.image.Source = await page.SourceStream.GetHalfImageAsync(isNextPage);
                        break;
                    }
                }

                if (mode == PageMode.AutoMerge)
                {
                    var right = this.pages.Where(k => k.Page == page.Page + 1).FirstOrDefault();
                    if (right != null)
                    {
                        this.config.Page = page.Page + ", " + right.Page;
                        this.image.Source = await page.SourceStream.ContactImageAsync(right.SourceStream);
                        break;
                    }
                }

                this.config.Page = page.Page.ToString();
                image.Source = await page.SourceStream.GetBitmapAsync();
                break;
            }
            while (false);
        }
        #endregion

        private async void rdoAutoMerge_Checked(object sender, RoutedEventArgs e)
        {
            if (this.pages != null && this.pages.Count > 0)
            {
                await this.SetImageAsync(this.pages.Where(k => k.Page == this.CurPage).FirstOrDefault(), true);
            }
        }
    }
}
